home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / stdio / StdioFileWriteProc.c < prev    next >
C/C++ Source or Header  |  1990-09-11  |  5KB  |  151 lines

  1. /* 
  2.  * StdioFileWriteProc.c --
  3.  *
  4.  *    Source code for the "StdioFileWriteProc" library procedure.
  5.  *
  6.  * Copyright 1988 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/StdioFileWriteProc.c,v 1.7 90/09/11 14:27:21 kupfer Exp $ SPRITE (Berkeley)"; 
  18. #endif not lint
  19.  
  20. #include "stdio.h"
  21. #include "fileInt.h"
  22. #include "stdlib.h"
  23. #include <errno.h>
  24. #include <unistd.h>
  25.  
  26. /*
  27.  * Before the first I/O on stdin, stdout, or stderr their buffers
  28.  * aren't initialized.  For the output streams, there must be someplace
  29.  * to buffer the first character, temporarily, until the buffer-flush
  30.  * routine is called.  That's what the variable below is for.
  31.  */
  32.  
  33. unsigned char stdioTempBuffer[4];
  34.  
  35. /*
  36.  * Stderr cannot have a dynamically allocated buffer since we may end
  37.  * up calling malloc at at bad time (like inside of panic in the kernel).
  38.  * Allocate a static buffer for stderr.
  39.  */
  40.  
  41. unsigned char stdioStderrBuffer[128];
  42.  
  43. /*
  44.  * Space is allocated here for the structures for stdin, stdout, and
  45.  * stderr, and also for the array that holds pointers to all the
  46.  * streams asociated with files.
  47.  */
  48.  
  49. FILE stdioInFile = {
  50.     0, 0, 0, 0, 0,
  51.     StdioFileReadProc, StdioFileWriteProc, StdioFileCloseProc,
  52.     (ClientData) 0, 0, STDIO_READ, NULL
  53. };
  54.  
  55. FILE stdioOutFile = {
  56.     stdioTempBuffer-1, 0, 0, stdioTempBuffer, 0,
  57.     StdioFileReadProc, StdioFileWriteProc, StdioFileCloseProc,
  58.     (ClientData) 1, 0, STDIO_WRITE, &stdioInFile
  59. };
  60.  
  61. FILE stdioErrFile = {
  62.     stdioTempBuffer-1, 0, 0, stdioTempBuffer, 0,
  63.     StdioFileReadProc, StdioFileWriteProc, StdioFileCloseProc,
  64.     (ClientData) 2, 0, STDIO_WRITE, &stdioOutFile
  65. };
  66.  
  67. FILE *stdioFileStreams = &stdioErrFile;
  68.  
  69. /*
  70.  *----------------------------------------------------------------------
  71.  *
  72.  * StdioFileWriteProc --
  73.  *
  74.  *    This procedure is invoked when the last character of space
  75.  *    in a stream's buffer is filled.  Its job is to write out the
  76.  *    contents of the buffer to the file system.  This procedure is
  77.  *    used for all streams that are associated with files (or pipes,
  78.  *    or anything for which the file-related system calls apply).
  79.  *
  80.  * Results:
  81.  *    None.
  82.  *
  83.  * Side effects:
  84.  *    If the buffer is REALLY full (which it isn't the first time
  85.  *    a byte is written to stdOut or stdErr:  we fake a full
  86.  *    condition to ensure that this procedure gets called so it
  87.  *    can do initialization), then the bytes in stream's buffer
  88.  *    are written to the stream's file.  The status and end-of-file
  89.  *    fields in stream are set if any problems occur.
  90.  *
  91.  *----------------------------------------------------------------------
  92.  */
  93.  
  94. void
  95. StdioFileWriteProc(stream, flush)
  96.     register FILE *stream;    /* Stream whose buffer needs to be emptied.
  97.                  * The stream must be writable.  The clientData
  98.                  * field of stream gives a stream index to
  99.                  * pass to the operating system. */
  100.     int flush;            /* Non-zero means it's important to really
  101.                  * write everything out.  Otherwise, this
  102.                  * procedure only needs to write things if
  103.                  * the buffer is full. */
  104. {
  105.     int count;
  106.  
  107.     /*
  108.      * If this stream doesn't have a buffer associated with it, create
  109.      * a new one, and retrieve the character just written (it was put in
  110.      * stdioTempBuffer).
  111.      */
  112.  
  113.     if (stream->bufSize == 0) {
  114.     stream->bufSize = BUFSIZ;
  115.     if ((stream == stderr) || (stream == stdout)) {
  116.         if (isatty((int) stream->clientData)) {
  117.         stream->flags |= STDIO_LINEBUF;
  118.         }
  119.     }
  120.     if (stream != stderr) {
  121.         stream->buffer = (unsigned char *) 
  122.             malloc((unsigned) stream->bufSize);
  123.     } else { 
  124.         stream->buffer = stdioStderrBuffer;
  125.         stream->bufSize = 128;
  126.     }
  127.     stream->lastAccess = stream->buffer;
  128.     *stream->buffer = stdioTempBuffer[0];
  129.     }
  130.  
  131.     count = stream->lastAccess + 1 - stream->buffer;
  132.     if ((count  == stream->bufSize) || flush) {
  133.     int    written;
  134.     stream->lastAccess = stream->buffer - 1;
  135.     do {
  136.         written = write((int) stream->clientData, (char *) stream->buffer, 
  137.         count);
  138.         if (written <= 0 ) {
  139.         stream->writeCount = 0;
  140.         stream->status = errno;
  141.         return;
  142.         }
  143.         count = count - written;
  144.     } while (count > 0);
  145.     stream->lastAccess = stream->buffer - 1;
  146.     stream->writeCount = stream->bufSize;
  147.     } else {
  148.     stream->writeCount = stream->bufSize - count;
  149.     }
  150. }
  151.